/*
===========================================================================
This source file is part of DyLab (Dynamic Laboratory)
For the latest info, see http://dylab.googlecode.com

Copyright (c) 2006-2008 Lukas Krejci
(krejci.lukas@volny.cz)

This file is part of DyLab.

    DyLab is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    DyLab is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with DyLab.  If not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/

//===========================================================================================
#include <dylab/utils/components/DynamicModule.h>
#include <dylab/utils/log/Log.h>
#include <dylab/utils/exceptions/EOperationFailed.h>

//===========================================================================================
#ifdef DYLAB_PLATFORM_WINDOWS
#   include <windows.h>
#   define DYLAB_DYNMODULE_NATIVE_HANDLE HMODULE
#endif

//===========================================================================================
dylab::DynamicModule::DynamicModule(const String & _name)
: mHandle(NULL), mName(_name)
{ 
}
//-----------------------------------------------------------------------------
dylab::DynamicModule::~DynamicModule()
{
    if (mHandle != NULL)
        release();
}
//-----------------------------------------------------------------------------
void dylab::DynamicModule::load()
{ DYLAB_TRACE_CALLS

    DYLAB_ASSERT(mHandle == NULL);

    String fullModuleName = mName + DYLAB_DYNMODULE_SUFFIX;
    DYLAB_LOG("Loading module: " + fullModuleName);

    // load the module
    mHandle = (DYLAB_DYNMODULE_HANDLE) DYLAB_DYNMODULE_LOAD(fullModuleName.c_str());

    if (mHandle == NULL)    
        throw EOperationFailed(String::fmt("Loading of the module '%1%' has failed.", mName));    
}
//-----------------------------------------------------------------------------
void dylab::DynamicModule::release()
{
    DYLAB_ASSERT(mHandle != NULL);
    DYLAB_LOG("Unloading module: " + mName);

    // unload the module
    if (DYLAB_DYNMODULE_UNLOAD((DYLAB_DYNMODULE_NATIVE_HANDLE)mHandle))
        throw EOperationFailed(String::fmt("Unloading of the module '%1%' has failed.", mName));

    mHandle = NULL;
}
//-----------------------------------------------------------------------------
void * dylab::DynamicModule::getSymbol(const String & _symbol)
{
    DYLAB_ASSERT(mHandle != NULL);

    // retrieve & return the required function
    return DYLAB_DYNMODULE_GETSYMBOL(static_cast<DYLAB_DYNMODULE_NATIVE_HANDLE>( mHandle ), _symbol.c_str());
}
//-----------------------------------------------------------------------------